package com.github.ylt.protocol.http;

import com.github.ylt.protocol.http.handler.HttpHandler;
import com.github.ylt.utils.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.Locale;

/**
 * http连接
 */
public class HttpConnection {
    private InputStream rawInputStream;
    private OutputStream rawOutputStream;
    private SocketChannel socketChannel;
    private SelectionKey selectionKey;
    private String protocol;
    private int remaining;
    private HttpHandler httpHandler;
    private boolean closed = false;
    public enum State{IDLE,CLOSED,REQUEST, RESPONSE,ACCEPTED}
    private volatile State state = State.IDLE;
    private long idleStartTime;
    private long requestStartTime;
    private long responseStartTime;
    private String path;

    private HttpContext context;

    public HttpConnection() {}

    public HttpConnection(String protocol, String path,HttpHandler httpHandler) {
        if(StringUtils.isEmpty(protocol) && StringUtils.isEmpty(path) && httpHandler == null){
            throw new NullPointerException("参数不能为空！");
        }
        if(path.charAt(0) != '/'){
            throw new IllegalArgumentException("path存在错误，path的第一个字符必须为/");
        }
        protocol = protocol.toUpperCase(Locale.ROOT);
        if(!"HTTP".equals(protocol)){
            throw new IllegalArgumentException("协议类型只能为HTTP，目前不支持HTTPS");
        }
        this.protocol = protocol;
        this.httpHandler = httpHandler;
    }

    public synchronized void close() {
            if(closed){
                return;
            }
            closed = true;
        try {
            if(rawInputStream != null){
                rawInputStream.close();
            }
            if(rawOutputStream != null){
                rawOutputStream.close();
            }
            if(socketChannel != null){
                socketChannel.close();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public HttpHandler getHttpHandler() {
        return httpHandler;
    }

    public void setHttpHandler(HttpHandler httpHandler) {
        if(httpHandler == null){
            throw new IllegalArgumentException("httpHandler不能为空");
        }
        if(this.httpHandler != null){
            throw  new IllegalArgumentException("httpHandler已经被设置，一个连接只能有一个Handler处理器");
        }
        this.httpHandler = httpHandler;
    }

    public void setRawInputStream(InputStream rawInputStream) {
        this.rawInputStream = rawInputStream;
    }

    public void setRawOutputStream(OutputStream rawOutputStream) {
        this.rawOutputStream = rawOutputStream;
    }

    public void setSocketChannel(SocketChannel socketChannel){
        this.socketChannel = socketChannel;
    }

    public SocketChannel getSocketChannel(){
        return this.socketChannel;
    }

    public State getState(){
        return this.state;
    }

    public void setState(State state){
        this.state = state;
    }

    public InputStream getRawInputStream() {
        return rawInputStream;
    }

    public OutputStream getRawOutputStream() {
        return rawOutputStream;
    }

    public SelectionKey getSelectionKey() {
        return selectionKey;
    }

    public String getProtocol() {
        return protocol;
    }

    public int getRemaining() {
        return remaining;
    }

    public long getIdleStartTime() {
        return idleStartTime;
    }

    public long getRequestStartTime() {
        return requestStartTime;
    }

    public long getResponseStartTime() {
        return responseStartTime;
    }

    public void setIdleStartTime(long idleStartTime) {
        this.idleStartTime = idleStartTime;
    }

    public void setRequestStartTime(long requestStartTime) {
        this.requestStartTime = requestStartTime;
    }

    public void setResponseStartTime(long responseStartTime) {
        this.responseStartTime = responseStartTime;
    }

    public void setSelectionKey(SelectionKey selectionKey) {
        this.selectionKey = selectionKey;
    }

    public HttpContext getContext() {
        return context;
    }

    public void setContext(HttpContext context) {
        this.context = context;
    }
}
